#ifndef _NAMED_TSET_H_
#define _NAMED_TSET_H_

#include <map>
#include <string>

#include <iostream>

namespace num
{
/// provides a container using CRC32 to generate Hashes of names
template <class KEY, class DATA> class NamedTSet
{
public:
	NamedTSet(bool DeleteSet = true) :
		m_DeleteSet(DeleteSet)
	{
		

	}
				
	virtual ~NamedTSet( )
	{
		if (m_DeleteSet)
		{
			ClearSet();
		}
	}


	void			ClearSet()
	{
		if (m_DeleteSet)
		{
			for (typename ElementMap::iterator It = m_Set.begin(); It != m_Set.end(); It++)
			{
				delete It->second;
			}
		}
		m_Set.clear();
	}

	/// add element to set
	bool			AddElement(KEY Key, DATA	Value)
	{
		if (!ElementExists(Key))
		{
		    m_Set.insert(ElementPair(Key, Value));
			return true;
		}
		return false;
	}
	/// check if element exists
	bool			ElementExists(KEY Key) const
	{
		if (GetElement(Key) != NULL)
			return true;
		return false;
	}	
	/// retrieve the element by Key.. usefull for caching the key
	DATA			GetElement(KEY Key) const
	{
		typename ElementMap::const_iterator It = m_Set.find(Key);
		if (It != m_Set.end()) return It->second;
		return NULL;
	}

	/// retrieve the element
	DATA			GetElementByIndex(int Index) const
	{
		if (Index < 0 || Index >= (int)m_Set.size()) return NULL;	// invalid
		for (typename ElementMap::const_iterator It = m_Set.begin(); It != m_Set.end(); It++)
		{
			if (Index == 0) 			
				return It->second;
			Index--;
		}
		return NULL;
	}
	/// delete the element
	void			RemoveElement(KEY key, bool Delete = true)
	{
		typename ElementMap::iterator It = m_Set.find(key);
		if (It != m_Set.end())
		{
			if (Delete && m_DeleteSet)
			{
				delete It->second;
			}
			m_Set.erase(It);
		}
	}

	/// number of elements
	unsigned long	GetElementC() const
	{
		return (unsigned long)m_Set.size();
	}

	typedef void	(*FindSetCB) (DATA, void* Data); // callback for effect param
	void			ForEach(FindSetCB pCB, void* Data)
	{
		for (typename ElementMap::iterator It = m_Set.begin(); It != m_Set.end(); It++)
		{
			pCB(It->second, Data);
		}
	}
protected:


	typedef std::map<KEY, DATA>			ElementMap;
	typedef std::pair<KEY, DATA>		ElementPair;

	ElementMap		m_Set;
	bool			m_DeleteSet;
};

} //namespace num
#endif  // _NAMED_TSET_H_
